# 44. 异常处理
# 异常处理
异常:一旦程序中发生了异常,那么程序就立刻停止,不继续执行下去
异常分为:异常跟错误
- 异常:Iteration 异常 在执行代码的过程中引发的异常
- 错误:Error 语法错误 比较明显的错误 在编译代码阶段就能检测出来
# 异常信息
常见的异常信息
- AttributeError:试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
- IOError: 输入/输出异常;基本上是无法打开文件
- ImportError: 无法引入模块或包;基本上是路径问题或名称错误
- IndentationError: 语法错误(的子类) ;代码没有正确对齐
- IndexError :下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
- KeyError: 试图访问字典里不存在的键
- KeyboardInterrupt: Ctrl+C被按下
- NameError: 使用一个还未被赋予对象的变量
- SyntaxError: Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
- TypeError: 传入对象类型与要求的不符合
- UnboundLocalError: 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它
- ValueError: 传入一个调用者不期望的值,即使值的类型是正确的
异常信息
这里就只说异常的名字,如果想了解,自行官网文档
异常名 | 异常名 | 异常名 |
---|---|---|
ArithmeticError | IndentationError | StandardError |
AssertionError | IndexError | StopIteration |
AttributeError | IOError | SyntaxError |
BaseException | KeyboardInterrupt | SyntaxWarning |
BufferError | KeyError | SystemError |
BytesWarning | LookupError | SystemExit |
DeprecationWarning | MemoryError | TabError |
EnvironmentError | NameError | TypeError |
EOFError | NotImplementedError | UnboundLocalError |
Exception | OSError | UnicodeDecodeError |
FloatingPointError | OverflowError | UnicodeEncodeError |
FutureWarning | PendingDeprecationWarning | UnicodeError |
GeneratorExit | ReferenceError | UnicodeTranslateError |
ImportError | RuntimeError | UnicodeWarning |
ImportWarning | RuntimeWarning | UserWarning |
Warning | ValueError | ZeroDivisionError |
# 简单的异常处理
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:a
请输入一个数字
## 这种异常处理:能够处理用户输入时,非数字的情况下,如果在外面在加个循环,报错后,在让用户输入,这样子,用户体验会相对更好
# 多分支异常处理
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
except IndexError:
print('您输入的数字无效')
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:6
您输入的数字无效
》》》:a
请输入一个数字
## 这样子,如果输入超范围的数字的报错,也截下来,转成自己输出的话,提高用户体验
# 万能异常
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
try:
user = int(input("》》》:"))
print(so[user-1])
except Exception:
print("您输入有误。。。。。")
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:6
您输入有误。。。。。
## 万能异常:Exception,Exception是所有异常的父类,可以说每个异常都是一个类,但异常的类都继承Exception,所以Exception能处理几乎所有的异常
# 万能异常和其他分支合作
注意:万能异常和其他分支合作,万能异常永远要放在所有except 异常的最后
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
while 1:
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
except Exception:
print("您输入有误。。。。。")
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:a
请输入一个数字
》》》:6
您输入有误。。。。。
为什么万能异常在放在其他异常的后面,这就要说到异常处理顺序
异常处理顺序:能 if判断 一样,一旦执行匹配到,就会立刻跳到匹配到的,不会在匹配接下来的
如果万能异常放在最上面,那下面还写不写异常有什么区别吗
# 异常处理的其他机制
# else
try中的代码正常执行 没有异常的时候会执行else中的代码
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
while 1:
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
except Exception:
print("您输入有误。。。。。")
else:
print("执行了%s功能"%so[user-1])
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:1
查看
执行了查看功能
# finally
无论try如何都会执行,无论在try中报的错,没有截到,程序要自动停止,finally还是会执行的
一般用处:操作系统资源归还的工作方面
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
while 1:
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
else:
print("执行了%s功能"%so[user-1])
finally:
print("无论try如何都会执行")
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:6
无论try如何都会执行
IndexError: list index out of range
## 就算是报错了,finally还是会执行
# 异常处理的执行顺序
try:
except:
try:
except:
else:
try:
except:
else:
finally:
try:
except:
finally:
try:
finally:
# 主动抛异常
raise 如果不指定抛出的错误,默认抛出截到的错误
注意:raise 指定抛出的错误只能是定义好的错误
## raise 默认抛出截到的错误
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
while 1:
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
raise
else:
print("执行了%s功能"%so[user-1])
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:a
请输入一个数字
ValueError: invalid literal for int() with base 10: 'a'
## raise 指定抛出错误
so = ["查看","删除","增加","修改"]
for i in enumerate(so,1):
print(i[0],i[1])
while 1:
try:
user = int(input("》》》:"))
print(so[user-1])
except ValueError:
print("请输入一个数字")
raise IndentationError
else:
print("执行了%s功能"%so[user-1])
执行结果:
1 查看
2 删除
3 增加
4 修改
》》》:a
请输入一个数字
IndentationError: None
## 直接抛出
raise IndentationError
执行结果:
IndentationError: None
# 自定义异常
格式:class 名称(Exception):Exception是所有异常错误类的父类
## 简单使用
class Customerror(Exception):
pass
raise Customerror
执行结果:
raise Customerror
__main__.Customerror
## 指定报错信息
class Customerror(Exception):
def __init__(self,msg):
self.msg = msg
raise Customerror("这是我自定义的异常错误")
执行结果:
raise Customerror("这是我自定义的异常错误")
__main__.Customerror: 这是我自定义的异常错误
## 想要自定义错误信息,就必须要有__init__这个方法跟msg这个参数的存在,参数名可自定义
# 断言
断言很简单:
断言是以布尔值为准,简单说,断言为True,接着执行下面的代码,断言为False,报错停止,不执行下面的代码
## 断言为True
print(11)
assert True
print(12)
执行结果:
11
12
## 断言为False
print(11)
assert False
print(12)
执行结果:
11
assert False
AssertionError
# 异常处理总结
- 尽量少用异常处理
- 能通过逻辑规避的应该代码逻辑规避掉
- 应该对某一句/几句话来进行处理